home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 076-100 / disk_077 / rawsamples / uuencode.d < prev   
Text File  |  1992-05-06  |  7KB  |  316 lines

  1. /*
  2.  * uuencode.drc
  3.  *   Encode a binary file into an ASCII representation that can be mailed
  4.  *   around. No blanks are sent - graves (`) are used instead. If only one
  5.  *   parameter is given on the run command, then that is the name of the
  6.  *   file to endcode. It's name is used as the target machine name, and
  7.  *   the encoded output is left in a file with the same name but with
  8.  *   '.uue' appended. No check is made for file names too long. If a
  9.  *   second parameter is given, it is the name to use for the target
  10.  *   machine file name. Any path names are stripped off of all except the
  11.  *   input file read and any explicit target machine name. Thus, the
  12.  *   output file will be created in the current directory.
  13.  *
  14.  *   This is a very early program, written before the Amiga version of Draco
  15.  *   had an I/O library and include files. Hence this source file is completely
  16.  *   self contained (except for the interface routines and assembler support).
  17.  */
  18.  
  19. uint
  20.     BUFF_SIZE = 10000,        /* nice and big */
  21.     MAX_BYTES = 45;        /* maximum bytes per encoded line */
  22.  
  23. ulong
  24.     MODE_READ = 1005,
  25.     MODE_WRITE = 1006;
  26.  
  27. type FileHandle_t = ulong;
  28.  
  29. extern
  30.     OpenDosLibrary(ulong version)*char,
  31.     CloseDosLibrary()void,
  32.     Output()FileHandle_t,
  33.     GetPars(*ulong pLen; **char pPtr)void,
  34.     DeleteFile(*char name)void,
  35.     Open(*char name; ulong mode)FileHandle_t,
  36.     Close(FileHandle_t fd)void,
  37.     Read(FileHandle_t fd; *byte buffer; ulong length)ulong,
  38.     Write(FileHandle_t fd; *char buffer; ulong length)ulong,
  39.     Exit(ulong status)void;
  40.  
  41. FileHandle_t StdOut, InFd, OutFd;
  42.  
  43. [BUFF_SIZE] byte InBuff;    /* buffer for input binary file */
  44. [BUFF_SIZE] char OutBuff;    /* buffer for output ASCII file */
  45. uint InMax, InPos, OutPos;    /* buffer positions and count */
  46. bool Eof;            /* true => end-of-file on input */
  47.  
  48. ulong ParLen;            /* used for parameter scanning */
  49. *char ParPtr;
  50.  
  51. /*
  52.  * writeString - write a string to standard output.
  53.  */
  54.  
  55. proc writeString(*char mess)void:
  56.     *char p;
  57.  
  58.     p := mess;
  59.     while p* ~= '\e' do
  60.     p := p + 1;
  61.     od;
  62.     if Write(StdOut, mess, p - mess) ~= p - mess then
  63.     Exit(40);
  64.     fi;
  65. corp;
  66.  
  67. /*
  68.  * flush -
  69.  *   Flush the contents of the output buffer to the output file.
  70.  */
  71.  
  72. proc flush()void:
  73.  
  74.     if OutPos ~= 0 then
  75.     if Write(OutFd, &OutBuff[0], OutPos) ~= OutPos then
  76.         writeString("Error on write - aborting.\n");
  77.         Exit(30);
  78.     fi;
  79.     OutPos := 0;
  80.     fi;
  81. corp;
  82.  
  83. /*
  84.  * addChar -
  85.  *   Add a single character to the output file, flushing if needed.
  86.  */
  87.  
  88. proc addChar(char ch)void:
  89.  
  90.     OutBuff[OutPos] := ch;
  91.     OutPos := OutPos + 1;
  92.     if OutPos = BUFF_SIZE then
  93.     flush();
  94.     fi;
  95. corp;
  96.  
  97. /*
  98.  * addString -
  99.  *   Add a string to the output file, using 'addChar'.
  100.  */
  101.  
  102. proc addString(*char st)void:
  103.  
  104.     while st* ~= '\e' do
  105.     addChar(st*);
  106.     st := st + 1;
  107.     od;
  108. corp;
  109.  
  110. /*
  111.  * encodeByte -
  112.  *   Encode a six-bit value as an ASCII char and add it to the output.
  113.  *   The main function is to replace blanks by graves.
  114.  */
  115.  
  116. proc encodeByte(byte b)void:
  117.  
  118.     addChar(if b = 0 then '`' else b + ' ' fi);
  119. corp;
  120.  
  121. /*
  122.  * getByte -
  123.  *   Get the next byte from the input binary file.
  124.  */
  125.  
  126. proc getByte()byte:
  127.  
  128.     if InPos = InMax then
  129.     InPos := 0;
  130.     InMax := Read(InFd, &InBuff[0], BUFF_SIZE);
  131.     if InMax = 0 then
  132.         Eof := true;
  133.     fi;
  134.     fi;
  135.     InPos := InPos + 1;
  136.     InBuff[InPos - 1]
  137. corp;
  138.  
  139. /*
  140.  * encode -
  141.  *   Encode the already opened input file into the already opened output
  142.  *   file, using the given remote system file name.
  143.  */
  144.  
  145. proc encode(*char remFileName)void:
  146.     *char p;
  147.     [MAX_BYTES] byte buff;
  148.     uint i, len;
  149.     byte b1, b2, b3;
  150.  
  151.     /* add the 'begin' line */
  152.     addString("begin 644 ");
  153.     addString(remFileName);
  154.     addChar('\n');
  155.     /* add the encoded binary file */
  156.     while not Eof do
  157.     /* get a bufferful (or however much is left to get) */
  158.     len := 0;
  159.     while not Eof and len ~= MAX_BYTES do
  160.         buff[len] := getByte();
  161.         if not Eof then
  162.         len := len + 1;
  163.         fi;
  164.     od;
  165.     /* first char on output line is encoded actual length */
  166.     encodeByte(len);
  167.     /* followed by up to MAX_BYTES * 4 / 3 characters of encoded data */
  168.     i := 0;
  169.     while i < len do
  170.         b1 := buff[i];
  171.         b2 := buff[i + 1];
  172.         b3 := buff[i + 2];
  173.         i := i + 3;
  174.         encodeByte(b1 >> 2);
  175.         encodeByte(b1 & 0x03 << 4 | b2 >> 4);
  176.         encodeByte(b2 & 0x0f << 2 | b3 >> 6);
  177.         encodeByte(b3 & 0x3f);
  178.     od;
  179.     /* and a newline */
  180.     addChar('\n');
  181.     od;
  182.     /* add the zero length terminator line so the UNIX version will live */
  183.     encodeByte(0);
  184.     addChar('\n');
  185.     /* add the 'end' line */
  186.     addString("end\n");
  187. corp;
  188.  
  189. /*
  190.  * parBump -
  191.  *   Move up one character in the command line tail.
  192.  */
  193.  
  194. proc parBump()void:
  195.  
  196.     ParPtr := ParPtr + 1;
  197.     ParLen := ParLen - 1;
  198. corp;
  199.  
  200. /*
  201.  * parSkipSpace -
  202.  *   Skip over any space in the command line tail.
  203.  */
  204.  
  205. proc parSkipSpace()void:
  206.  
  207.     while ParLen ~= 0 and
  208.         (ParPtr* = ' ' or ParPtr* = '\n' or ParPtr* = '\r') do
  209.     parBump();
  210.     od;
  211. corp;
  212.  
  213. /*
  214.  * parGetName -
  215.  *   Isolate a name from the command tail.
  216.  */
  217.  
  218. proc parGetName()void:
  219.  
  220.     while ParLen ~= 0 and ParPtr* ~= ' ' and ParPtr* ~= '\n' do
  221.     parBump();
  222.     od;
  223.     ParPtr* := '\e';
  224.     parBump();
  225. corp;
  226.  
  227. /*
  228.  * main -
  229.  *   The main program. Get the command line parameters, parse them, open
  230.  *   files as needed and pass the remote file name to 'encode'.
  231.  */
  232.  
  233. proc main()void:
  234.     *char inFileName, remFileName;
  235.     [60] char nameBuffer;
  236.     *char p, q;
  237.  
  238.     if OpenDosLibrary(0) ~= nil then
  239.     StdOut := Output();
  240.     GetPars(&ParLen, &ParPtr);
  241.     parSkipSpace();
  242.     if ParLen = 0 then
  243.         writeString("usage: uuencode localFileName [remoteFileName]\n");
  244.     else
  245.         inFileName := ParPtr;
  246.         parGetName();
  247.         parSkipSpace();
  248.         /* find the final simple name of the given input name */
  249.         p := inFileName;
  250.         while p* ~= '\e' do
  251.         p := p + 1;
  252.         od;
  253.         while p ~= inFileName and p* ~= '/' do
  254.         p := p - 1;
  255.         od;
  256.         if p* = '/' then
  257.         p := p + 1;
  258.         fi;
  259.         if ParLen = 0 then
  260.         /* if no explicit remote file name is given, use the tail of
  261.            the input file name. */
  262.         remFileName := p;
  263.         else
  264.         remFileName := ParPtr;
  265.         parGetName();
  266.         fi;
  267.         /* make a copy of input name so that we can append .uue to it */
  268.         q := &nameBuffer[0];
  269.         while
  270.         q* := p*;
  271.         p* ~= '\e'
  272.         do
  273.         p := p + 1;
  274.         q := q + 1;
  275.         od;
  276.         p := ".uue";
  277.         while
  278.         q* := p*;
  279.         p* ~= '\e'
  280.         do
  281.         p := p + 1;
  282.         q := q + 1;
  283.         od;
  284.         /* open files, etc. */
  285.         InFd := Open(inFileName, MODE_READ);
  286.         if InFd = 0 then
  287.         writeString("Can't open input file '");
  288.         writeString(inFileName);
  289.         writeString("'\n");
  290.         Exit(10);
  291.         fi;
  292.         DeleteFile(&nameBuffer[0]);
  293.         OutFd := Open(&nameBuffer[0], MODE_WRITE);
  294.         if OutFd = 0 then
  295.         writeString("Can't open/create output file '");
  296.         writeString(&nameBuffer[0]);
  297.         writeString("'\n");
  298.         Close(InFd);
  299.         Exit(20);
  300.         fi;
  301.         /* initialize */
  302.         Eof := false;
  303.         InMax := 0;
  304.         InPos := 0;
  305.         OutPos := 0;
  306.         /* go encode the file */
  307.         encode(remFileName);
  308.         /* flush output buffer, and close files */
  309.         flush();
  310.         Close(OutFd);
  311.         Close(InFd);
  312.     fi;
  313.     CloseDosLibrary();
  314.     fi;
  315. corp;
  316.